home *** CD-ROM | disk | FTP | other *** search
/ Whiteline: delta / whiteline CD Series - delta.iso / document / hypertxt / ximgtool / l3decode.c < prev    next >
C/C++ Source or Header  |  1995-11-25  |  4KB  |  98 lines

  1. #include "imgcodec.h"
  2.  
  3. /* Here is the one and only Level-3 decoder...
  4.  * It is designed to be efficient as well as flexible in usage,
  5.  * and it is capable of decoding all Level 1, 2, and 3 image files
  6.  * without explicitly checking for level number of input stream.
  7.  * So this one decoder is really sufficient, there is no need for
  8.  * lower level decoders. In fact, a lower level decoder could be
  9.  * programmed somewhat more straightforward by assuming, that the
  10.  * line limit is not reached during inner decoding loops, but this
  11.  * approach would have the disadvantage to loose reliability on
  12.  * messy input data. The Level-3 decoder, however, automatically
  13.  * checks for buffer overflows at any time, so it is the most
  14.  * reliable and should work without any problems on arbitrary
  15.  * messy data input.
  16.  *
  17.  * Aside from getting away with any line limit coding (but going
  18.  * on to require only a single line buffer by the given decoding
  19.  * scheme!), Level-3 provides an 'extended vertical run mode',
  20.  * which is introduced with Level-2. This is quite easy to
  21.  * implement in the decoder, and is also easy to exploit in
  22.  * encoding. It may save a lot of bytes on certain images,
  23.  * especially desktop snapshots or line drawings.
  24.  * This mode places a run code in the stream for a series of bytes
  25.  * in the line that equals the above line. This may be considered
  26.  * as a generalization of the known 'vertical run code', which is
  27.  * used for (multiple) full line repeats. This vrc has a 'stuffed
  28.  * prefix byte' (0xFF), and the new generalized vertical run is
  29.  * introduced as an extension of this stuffing byte by allowing it
  30.  * to be an arbitrary value to be 0xFF for known full vrc and the
  31.  * extended vertical run count minus one else. The 'minus one'
  32.  * allows the real run count to be from 1 to 255 (0 is not needed,
  33.  * and so is reserved for full vrc), which is also straightforward
  34.  * to implement.
  35.  * Implementation of extended vrc is very easy and efficient by
  36.  * simply skipping the line output buffer bytewise runcount times.
  37.  * This, however, assumes, that the line buffer always contains
  38.  * the last decoded bytes. But this is easy to guarantee by only
  39.  * forbid the put_line function to change the buffer contents.
  40.  *
  41.  * Furthermore, the Level-3 as well as Level-2 extends the meaning
  42.  * of byte string and full vrc counts. We consider a zero value to
  43.  * be a count of 256. This is straightforward to implement in the
  44.  * decoder by using a do-while-decrement loop, without additional
  45.  * code. The encoders can also take care of this easily.
  46.  *
  47.  * The decoder is implemented as endless loop for processing data.
  48.  * Conditions for breakdown are assumed to be checked within the
  49.  * callback functions (data_func and put_line) and to be handled
  50.  * via a standard setjmp/longjmp scheme. This approach avoids
  51.  * additional checking code in the decoder loop. If it should be
  52.  * unlikely, it is possible to define the callback functions as
  53.  * returning a boolean continue/abort value and adapt the decoder.
  54.  * But, again, the actual approach is more compact and efficient.
  55.  */
  56.  
  57. void level_3_decode(FBUFPUB *input, IBUFPUB *image)
  58. {
  59.   char cdata, c_val, *pat_ptr;
  60.   short i;
  61.  
  62.   for (;;)
  63.   {
  64.     FGETC(input, cdata);
  65.     if ((c_val = cdata) != 0)
  66.     {
  67.       if (cdata <<= 1)                  /* solid run */
  68.       {
  69.     c_val >>= 7;
  70.     do IPUTC(image, c_val); while (cdata -= 2);
  71.       }
  72.       else                    /* byte string */
  73.       {
  74.     FGETC(input, cdata);
  75.     do FICOPYC(input, image); while (--cdata);
  76.     } }
  77.     else
  78.     {
  79.       FGETC(input, cdata);
  80.       if (cdata)                /* pattern run */
  81.       {
  82.     pat_ptr = image->pat_buf;
  83.     for (i = image->pat_run; --i >= 0;)
  84.       FGETC(input, *pat_ptr++);
  85.     do
  86.     { pat_ptr = image->pat_buf;
  87.       for (i = image->pat_run; --i >= 0;)
  88.         IPUTC(image, *pat_ptr++);
  89.     }
  90.     while (--cdata);
  91.       }
  92.       else                   /* vertical replication */
  93.       {
  94.     FGETC(input, cdata);
  95.     if (++cdata) do ISKIPC(image); while (--cdata);
  96.     else FGETC(input, image->vrc);
  97. } } } }
  98.